home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / System7 tools / R / RequiredAE XCMD ƒ / source / hyperUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-11  |  8.7 KB  |  360 lines  |  [TEXT/KAHL]

  1. /***
  2.  * hyperUtil.c
  3.  *
  4.  *  Some useful routine for writing hypercard xcmds and funcs.
  5.  *
  6.  *  Gordon Watts July '91 Copyright.
  7.  *
  8.  ***/
  9. #include <HyperXCmd.h>
  10. #include "hyperUtil.h"
  11. #include <Aliases.h>
  12. /**
  13.  * strToHandle
  14.  *
  15.  *  Convert a null terminated string to a handle to pass back to hypercard.
  16.  *
  17.  **/
  18. Handle strToHandle (XCmdPtr theP, char *theString)
  19. {
  20.     Handle theHandle;
  21.     register Size theLen = StringLength (theP, theString) + 1;
  22.  
  23.     theHandle = NewHandle (theLen);
  24.     BlockMove (theString, *theHandle, theLen);
  25.     
  26.     return theHandle;
  27. }
  28. /**
  29.  * HCProgramToPortAndLoc
  30.  *
  31.  *  Convert a Hypercard program name (<zone>:<mac>:<program>) to a
  32.  *  port.  If that program has more than one port open, we take the
  33.  *  first port we find!
  34.  *
  35.  *  Assumptions we make:
  36.  *
  37.  **/
  38. OSErr HCProgramToPortAndLoc (char *theName, LocationNameRec *theLoc,
  39.     PortInfoRec *thePort)
  40. {
  41.     char *appleZone = 0;
  42.     char *macName = 0;
  43.     char *progName = 0;
  44.     char *theLastChar = 0;
  45.     PPCPortRec thePortSearchSpec;
  46.     IPCListPortsPBRec thePBRec;
  47.     int theErr;
  48.  
  49.     /**
  50.      ** Assemble a location.  This is a bit of a pain, as we must
  51.      ** carefully unpack the incomming string...
  52.      **/
  53.     
  54.     /**
  55.      ** First job -- find the end of the incomming string so we don't
  56.      ** run off into memory...
  57.      **/
  58.     
  59.     theLastChar = theName;
  60.     appleZone = theName;            /* First thing there... */
  61.     while (*theLastChar != '\0') {
  62.         if (*theLastChar == ':') {
  63.             if (!macName) {
  64.                 macName = theLastChar + 1;
  65.             } else if (!progName) {
  66.                 progName = theLastChar + 1;
  67.             }
  68.         }
  69.         theLastChar++;
  70.     }
  71.     
  72.     /**
  73.      ** Right, make sure that we got everything...
  74.      **/
  75.     
  76.     if ((progName == 0) || (macName == 0))
  77.         return 1;        /* Random error... */
  78.  
  79.     /**
  80.      ** Next, assemble a port record that we can use to specify what
  81.      ** the hell we are looking for...  Use a roman script (sorry, guys),
  82.      ** match only names that have our program, and match all types.
  83.      ** That way we will get the first type.
  84.      **/
  85.     
  86.     thePortSearchSpec.nameScript = smRoman;
  87.     thePortSearchSpec.portKindSelector = ppcByString;
  88.     MakePascalStringWLen ((StringPtr) thePortSearchSpec.name, 32, progName,
  89.             (Size)(theLastChar - progName));
  90.     MakePascalStringWLen ((StringPtr) thePortSearchSpec.u.portTypeStr,
  91.             32, "=", 1);
  92.  
  93.     /**
  94.      ** Next job is to fill in the location record that the guy passed
  95.      ** in.  The objString is the mac we wish to connect to.  The zone
  96.      ** is the apple zone.  We let the type be random...  so we set it
  97.      ** to PPCToolBox as defined by IM VI 6 7-23.
  98.      **/
  99.     
  100.     theLoc -> locationKindSelector = ppcNBPLocation;
  101.     {
  102.         register EntityName *theE = &(theLoc -> u.nbpEntity);
  103.         
  104.         MakePascalStringWLen ((StringPtr) &(theE -> objStr), 32,
  105.                     macName, (int) (progName - macName - 1));
  106.         MakePascalStringWLen ((StringPtr) &(theE -> typeStr), 32,
  107.                     "PPCToolBox", 10);
  108.         MakePascalStringWLen ((StringPtr) &(theE -> zoneStr), 32,
  109.                     appleZone, (macName - appleZone - 1));
  110.     }
  111.  
  112.     /**
  113.      ** Right.  Finally, we fill in the parameter block we are to pass
  114.      ** to IPCListPorts.
  115.      **/
  116.     
  117.     thePBRec.startIndex = 0;
  118.     thePBRec.requestCount = 1;
  119.     thePBRec.portName = &thePortSearchSpec;
  120.     thePBRec.locationName = theLoc;
  121.     thePBRec.bufferPtr = thePort;
  122.  
  123.     /**
  124.      ** Call the damm routine and try to get the stupid port back!
  125.      **/
  126.  
  127.     theErr = IPCListPorts (&thePBRec, false);
  128.  
  129.     return theErr;
  130. }
  131.  
  132. /**
  133.  * MakePascalStringWLen
  134.  *
  135.  *  Given a C string, put it into a pascal storage area.  We also make
  136.  *  sure that the length of the pascal string isn't too long (the caller
  137.  *  specifiys the longest length possible).  We are passed in the length
  138.  *  of the C string... This makes our life simpler...
  139.  *
  140.  **/
  141. void MakePascalStringWLen (StringPtr theDest, int theDestLen, char *theSrc,
  142.     int theSrcLen)
  143. {
  144.     theDest[0] = theSrcLen > theDestLen ? theDestLen : theSrcLen;
  145.     BlockMove (theSrc, &(theDest[1]), theDest[0]);
  146. }
  147.  
  148. /**
  149.  * AEFromHCProgram
  150.  *
  151.  *  Given a HC program name, turn it into an apple event.  This isn't
  152.  *  too bad; we just have to fool a little with the descriptor types.
  153.  *  Code thanks to Kevin at Apple.
  154.  **/
  155. #define nice
  156. OSErr AEFromHCProgram (StringPtr theHCProgName,
  157.     AEEventClass theClass,
  158.     AEEventID theEventID, int returnID, long transactionID,
  159.     AppleEvent *theAE)
  160. {
  161. #ifdef nice
  162.     AEDesc    theAddressDesc;
  163.     register int theErr;
  164.  
  165.     /**
  166.      ** Convert the string into a descriptor & try and make it
  167.      ** into a better type recrod...  By passing 'ADDR' as the type
  168.      ** into which we wish to convert the darned string, we let the mac
  169.      ** os (PPC Toolbox) decide if we should do a process serial number or
  170.      ** a real targetID record (for networked destinations).
  171.      **/
  172.     
  173.     theErr = AECoercePtr (typeChar, (Ptr) &(theHCProgName[1]),
  174.             theHCProgName[0], 'ADDR', &theAddressDesc);
  175.     if (theErr != noErr)
  176.         return theErr;
  177.  
  178.     /**
  179.      ** Hey!  Next job: create the apple event.  Pretty easy, eh?
  180.      **/
  181.  
  182.     theErr = AECreateAppleEvent (theClass, theEventID, &theAddressDesc,
  183.         returnID, transactionID, theAE);
  184.  
  185.     /**
  186.      ** Delete the address descriptor and return.
  187.      **/
  188.     
  189.     return theErr;
  190. #endif
  191. #ifdef dumy_too
  192.     register int theErr;
  193.     TargetID theTarget;
  194.     PortInfoRec thePortInfo;
  195.     char string[255];
  196.     AEAddressDesc targetDesc;
  197.  
  198.     /**
  199.      ** Ok.. First job is to convert the thing into location and port
  200.      ** records...
  201.      **/
  202.     
  203.     BlockMove (&(theHCProgName[1]), string, theHCProgName[0]);
  204.     string[theHCProgName[0]] = 0;
  205.     
  206.     theErr = HCProgramToPortAndLoc (string, &(theTarget.location),
  207.              &thePortInfo);
  208.     if (theErr != noErr)
  209.         return theErr;
  210.     
  211.     /**
  212.      ** Next, put the mac name into the target guy...
  213.      **/
  214.     
  215.     theTarget.name = thePortInfo.name;
  216.     
  217.     /**
  218.      ** Next, create a descriptor to hold this thing...
  219.      **/
  220.     
  221.     theErr = AECreateDesc (typeTargetID, (Ptr) &theTarget,
  222.         sizeof(TargetID), &targetDesc);
  223.     if (theErr != noErr)
  224.         return theErr;
  225.     
  226.     /**
  227.      ** Right on.  Now we get to create the apple event...
  228.      **/
  229.  
  230.     theErr = AECreateAppleEvent (theClass, theEventID, &targetDesc,
  231.         returnID, transactionID, theAE);
  232.     return theErr;
  233. #endif
  234. }
  235.  
  236. /**
  237.  * makeFileListFmHCF
  238.  *
  239.  *  Make a apple event file descriptor list from a hypercard field.  This
  240.  *  means that we expect all the fields to be <return> seperated (we
  241.  *  use call back routines to figure out what the file names are...).
  242.  *
  243.  **/
  244. OSErr makeFileListFmHCF (XCmdPtr paramPtr, char *cfile_list,
  245.         AEDescList *theFileDL)
  246. {
  247.     register int theErr, index;
  248.     char *nextFile;
  249.     Str255 aFileName, fullFileName;
  250.     SFTypeList theTypes;
  251.     OSType theFileType;
  252.     FSSpec myFS;
  253.     AliasHandle myAlias;
  254.     AEDesc theAliasDesc;
  255.  
  256.     /**
  257.      ** First, create the descriptor header...
  258.      **/
  259.     
  260.     theErr = AECreateList (0L, 0, false, theFileDL);
  261.     if (theErr != noErr)
  262.         return theErr;
  263.     
  264.     /**
  265.      ** Loop through all return delimited filenames in the input string.
  266.      ** For each one, we must convert it to a typeFSS record and then
  267.      ** we can use it to coerce to a typeAlias descriptor which can
  268.      ** be send to the other guys in this world...
  269.      **/
  270.     
  271.     nextFile = cfile_list;
  272.     index = 0;
  273.  
  274.     while (*nextFile != '\0') {
  275.  
  276.         ReturnToPas (paramPtr, nextFile, aFileName);
  277.         ScanToReturn (paramPtr, &nextFile);
  278.         if (*nextFile != 0) nextFile++;
  279.  
  280.         theFileType = '    ';
  281.  
  282.         /**
  283.          ** Try to make the FSSpec from the file.  If we fail, then
  284.          ** ask the user to point out the file to us.
  285.          **/
  286.  
  287.         theErr = FSMakeFSSpec (0, 0, aFileName, &myFS);
  288.         {
  289.             Str255 theNum;
  290.             
  291.             NumToStr (paramPtr, theErr, theNum);
  292.             SetGlobal (paramPtr, (StringPtr) "\ptheErrFS",
  293.                 PasToZero (paramPtr, theNum));
  294.         }
  295.  
  296.         if (theErr != noErr) {
  297.             if (GetFilePath(paramPtr, (StringPtr) aFileName, 0, theTypes,
  298.                          true, &theFileType, (StringPtr) fullFileName))
  299.                 theErr = FSMakeFSSpec (0, 0, fullFileName, &myFS);
  300.         }
  301.         if (theErr != noErr)
  302.             return theErr;
  303.  
  304.         index++;
  305.  
  306.         /**
  307.          ** Next, create an alias type o record...
  308.          **/
  309.         
  310.         theErr = NewAlias (0L, &myFS, &myAlias);
  311.         if (theErr != noErr)
  312.             return theErr;
  313.         
  314.         /**
  315.          ** And add it to the list...
  316.          **/
  317.  
  318.         theErr = AEPutPtr (theFileDL, index, typeAlias, (Ptr) *myAlias,
  319.                 GetHandleSize ((Handle) myAlias));
  320.         if (theErr != noErr)
  321.             return theErr;
  322.         
  323.         {
  324.             AEDesc theJunk;
  325.             Str255 string;
  326.             ProcPtr proc, proc1;
  327.             long refcon;
  328.             Boolean isdesc;
  329.             
  330. /*            theErr = AECreateDesc (typeFSS, (Ptr) &myFS, sizeof (FSSpec),
  331.                 &theJunk);
  332. */            
  333.             theErr = AECoercePtr (typeFSS, (Ptr) &myFS, sizeof(FSSpec),
  334.                 typeAlias, &theJunk);
  335.             NumToStr (paramPtr, theErr, string);
  336.             SetGlobal (paramPtr, (StringPtr) "\ptheErrC",
  337.                 PasToZero (paramPtr, string));
  338.             proc = 0;
  339.             theErr = AEGetCoercionHandler (typeFSS, typeAlias,
  340.                 &proc, &refcon, &isdesc, false);
  341.             proc1 = 0;
  342.             theErr = AEGetCoercionHandler (typeAlias, typeFSS,
  343.                 &proc1, &refcon, &isdesc, true);
  344.             BoolToStr (paramPtr, ((proc1 != 0) || (proc != 0)), string);
  345.             SetGlobal (paramPtr, (StringPtr) "\phandlerIs",
  346.                 PasToZero (paramPtr, string));
  347.         }
  348.     }
  349.  
  350.     /**
  351.      ** Some basic error checking -- make sure we sent something...
  352.      **/
  353.  
  354.     if (index) {
  355.         return noErr;
  356.     } else {
  357.         return 1;
  358.     }
  359. }
  360.